package com.whfc.mach.service.impl;

import com.alibaba.fastjson.JSON;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.whfc.common.enums.DeviceType;
import com.whfc.common.exception.BizException;
import com.whfc.common.file.FileHandler;
import com.whfc.common.file.FilePathConfig;
import com.whfc.common.file.properties.FileExpirationRules;
import com.whfc.common.result.ListData;
import com.whfc.common.result.PageData;
import com.whfc.common.result.ResultEnum;
import com.whfc.common.util.*;
import com.whfc.fuum.service.SysDeptService;
import com.whfc.mach.dao.AppMachDayMapper;
import com.whfc.mach.dao.AppMachMonthMapper;
import com.whfc.mach.dao.AppMachMonthReportMapper;
import com.whfc.mach.dao.AppMachWeekReportMapper;
import com.whfc.mach.dto.*;
import com.whfc.mach.dto.report.AppMachReportDTO;
import com.whfc.mach.dto.report.AppMachWeekReportDTO;
import com.whfc.mach.dto.report.MachReportDataDTO;
import com.whfc.mach.dto.report.WeekReportDetailDTO;
import com.whfc.mach.entity.AppMachMonthReport;
import com.whfc.mach.entity.AppMachWeekReport;
import com.whfc.mach.service.AppReportService;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.annotation.DubboService;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.util.CellRangeAddress;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.scheduling.annotation.Async;

import java.io.*;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author sun_guodong
 * @description
 * @date 2021-03-10
 */
@DubboService(interfaceClass = AppReportService.class, version = "1.0.0")
public class AppReportServiceImpl implements AppReportService {
    private Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    private AppMachWeekReportMapper weekReportMapper;

    @Autowired
    private AppMachMonthReportMapper monthReportMapper;

    @Autowired
    private AppMachDayMapper machDayMapper;

    @Autowired
    private AppMachMonthMapper machMonthMapper;

    @DubboReference(interfaceClass = SysDeptService.class, version = "1.0.0")
    private SysDeptService sysDeptService;

    @Autowired
    private FileHandler fileHandler;

    @Autowired
    private FilePathConfig filePathConfig;

    /**
     * 临时文件目录
     */
    private static final String PATH = "mach/tmp";

    /**
     * 项目id
     */
    private static final Integer ADSQ_PROJECT_ID = 130;

    /**
     * 年份的字符串
     */
    private static final String YEAR_STR = "%S-00-00";

    @Override
    public PageData<MachDayDataDTO> dayReport(List<Integer> deptIds, Date date, Integer pageNum, Integer pageSize) throws BizException {
        logger.info("设备日报服务,deptIds:{},date:{},pageNum:{},pageSize:{}", deptIds, date, pageNum, pageSize);
        PageHelper.startPage(pageNum, pageSize);
        List<MachDayDataDTO> list = machDayMapper.selectMachDayDataDTO(deptIds, date);
        PageHelper.clearPage();
        return PageUtil.pageData(PageInfo.of(list));
    }

    @Override
    public ListData<MachDayDataDTO> dayReport(List<Integer> deptIds, Date startDate, Date endDate) throws BizException {
        logger.info("小程序设备报表数据类别服务,deptIds:{},startDate:{},endDate:{}", deptIds, startDate, endDate);
        List<MachDayDataDTO> list = machDayMapper.selectMachAvgDataDTO(deptIds, startDate, endDate);
        return new ListData<>(list);
    }

    @Override
    public PageData<MachMonthReportDTO> monthReport(List<Integer> deptIds, Integer pageNum, Integer pageSize, Date startDate, Date endDate) throws BizException {
        logger.info("设备月报服务,deptIds:{},pageNum:{},pageSize:{},startDate:{},endDate:{}",
                deptIds, pageNum, pageSize, startDate, endDate);
        PageHelper.startPage(pageNum, pageSize);
        List<MachMonthReportDTO> machList = machDayMapper.selectMonthReportMach(deptIds, startDate, endDate);
        PageHelper.clearPage();
        if (machList.size() == 0) {
            return PageUtil.pageData(PageInfo.of(Collections.EMPTY_LIST));
        }
        List<Integer> machIds = new ArrayList<>(machList.size());
        for (MachMonthReportDTO monthReportDTO : machList) {
            machIds.add(monthReportDTO.getMachId());
        }

        List<MachDayDataDTO> list = machDayMapper.selectMonthReportByMachIds(machIds, startDate, endDate);
        for (MachMonthReportDTO monthReportDTO : machList) {
            this.setDayList(monthReportDTO, list, startDate, endDate);
        }

        return PageUtil.pageData(PageInfo.of(machList));
    }

    @Override
    public PageData<MachMonthReportDTO> yearReport(List<Integer> deptIds, Integer pageNum, Integer pageSize, int year) throws BizException {
        logger.info("设备年报服务,deptIds:{},pageNum:{},pageSize:{},year:{}", deptIds, pageNum, pageSize, year);
        PageHelper.startPage(pageNum, pageSize);
        List<MachMonthReportDTO> machList = machMonthMapper.selectYearReportMach(deptIds, String.format(YEAR_STR, year));
        PageHelper.clearPage();
        if (machList.size() == 0) {
            return PageUtil.pageData(PageInfo.of(Collections.EMPTY_LIST));
        }
        List<Integer> machIds = new ArrayList<>(machList.size());
        for (MachMonthReportDTO monthReportDTO : machList) {
            machIds.add(monthReportDTO.getMachId());
        }
        List<MachDayDataDTO> list = machMonthMapper.selectMonthReportByMachIds(machIds, String.format(YEAR_STR, year));
        for (MachMonthReportDTO monthReportDTO : machList) {
            this.setMonthList(monthReportDTO, list, year);
        }
        return PageUtil.pageData(PageInfo.of(machList));
    }


    @Override
    public AppMachDataStatDTO reportStat(List<Integer> deptIds, Date startDate, Date endDate) throws BizException {
        logger.info("设备报表统计服务,deptIds:{},startDate:{},endDate:{}", deptIds, startDate, endDate);
        AppMachDataStatDTO data = machDayMapper.selectAvgData(deptIds, startDate, endDate);
        return data;
    }

    @Override
    public AppMachDataStatDTO yearReportStat(List<Integer> deptIds, Integer year) throws BizException {
        logger.info("设备年报统计服务,deptIds:{},year:{}", deptIds, year);
        AppMachDataStatDTO data = machMonthMapper.selectAvgData(deptIds, String.format(YEAR_STR, year));
        return data;
    }

    @Override
    @Async
    public void statMachMonthData(List<Integer> deptIds, Date monthBegin, Date monthEnd) throws BizException {
        logger.info("统计设备每月数据服务,deptIds:{},monthBegin:{},monthEnd:{}", deptIds, monthBegin, monthEnd);
        List<AppMachDataStatDTO> list = machDayMapper.selectAvgDataByDeptIds(deptIds, monthBegin, monthEnd);
        if (list.size() == 0) {
            return;
        }
        machMonthMapper.batchInsert(DateUtil.formatDate(monthBegin, "yyyy-MM"), list);
    }

    @Override
    public String dayReportExport(Integer deptId, Date date, Integer deviceType) throws BizException {
        logger.info("导出设备日报服务,deptId:{},date:{},deviceType:{}", deptId, date, deviceType);
        String name = filePathConfig.getFilePath(PATH, RandomUtil.getRandomFileName(), "xls");
        // 获取要导出的数据
        List<Integer> deptIds = sysDeptService.getDescendantDeptIdList(deptId);
        List<MachDayDataDTO> list = machDayMapper.selectMachDayDataDTO(deptIds, date);
        if (list.isEmpty()) {
            throw new BizException(ResultEnum.FAILURE.getCode(), "该设备日报无数据");
        }

        String path = "";
        try {
            path = this.export2DayReportExcel(deptId, list, name, date, deviceType);
        } catch (Exception e) {
            logger.error("导出设备日报失败,{}", e);
        }
        return path;
    }

    @Override
    public String monthReportExport(Integer deptId, Date startDate, Date endDate, Integer deviceType) throws BizException {
        logger.info("导出设备月报服务,deptId:{},startDate:{},endDate:{},deviceType:{}", deptId, startDate, endDate, deviceType);
        String name = filePathConfig.getFilePath(PATH, RandomUtil.getRandomFileName(), "xls");
        // 获取数据
        List<Integer> deptIds = sysDeptService.getDescendantDeptIdList(deptId);
        if (deptIds == null || deptIds.size() == 0) {
            throw new BizException(ResultEnum.FAILURE.getCode(), "该设备月报无数据");
        }
        List<MachMonthReportDTO> machList = machDayMapper.selectMonthReportMach(deptIds, startDate, endDate);
        if (machList.size() == 0) {
            throw new BizException(ResultEnum.FAILURE.getCode(), "该设备月报无数据");
        }

        List<Integer> machIds = machList.stream().map(mach -> mach.getMachId()).collect(Collectors.toList());
        List<MachDayDataDTO> list = machDayMapper.selectMonthReportByMachIds(machIds, startDate, endDate);
        for (MachMonthReportDTO monthReportDTO : machList) {
            this.setDayList(monthReportDTO, list, startDate, endDate);
        }

        // 表头
        String startDateStr = DateUtil.formatDate(startDate, "yyyy年MM月dd日");
        String endDateStr = DateUtil.formatDate(endDate, "yyyy年MM月dd日");
        String headline = String.format("%s 设备报表", startDateStr + "-" + endDateStr);

        String path = "";
        try {
            path = this.export2MonthReportExcel(deptId, name, headline, machList, deviceType);
        } catch (Exception e) {
            logger.error("导出设备月报失败,{}", e);
        }
        return path;
    }

    @Override
    public String yearReportExport(Integer deptId, Integer year) throws BizException {
        logger.info("导出设备年报服务,deptId:{},year:{}", deptId, year);
        String yearStr = String.format(YEAR_STR, year);
        String name = filePathConfig.getFilePath(PATH, RandomUtil.getRandomFileName(), "xls");

        // 获取数据
        List<Integer> deptIds = sysDeptService.getDescendantDeptIdList(deptId);
        if (deptIds == null || deptIds.size() == 0) {
            throw new BizException(ResultEnum.FAILURE.getCode(), "该设备年报无数据");
        }
        List<MachMonthReportDTO> machList = machMonthMapper.selectYearReportMach(deptIds, yearStr);
        if (machList.size() == 0) {
            throw new BizException(ResultEnum.FAILURE.getCode(), "该设备年报无数据");
        }
        List<Integer> machIds = machList.stream().map(mach -> mach.getMachId()).collect(Collectors.toList());
        List<MachDayDataDTO> list = machMonthMapper.selectMonthReportByMachIds(machIds, yearStr);
        for (MachMonthReportDTO monthReportDTO : machList) {
            this.setMonthList(monthReportDTO, list, year);
        }

        // 表头
        String headline = String.format("%s年设备年报", year);
        String path = "";
        try {
            path = this.export2MonthReportExcel(deptId, name, headline, machList, DeviceType.obd.getValue());
        } catch (Exception e) {
            logger.error("导出电力设备年报失败,{}", e);
        }
        return path;
    }


    @Override
    public PageData<AppMachReportDTO> getDayReportDataList(List<Integer> deptIds, Date startDate, Date endDate, Integer pageNum, Integer pageSize) {
        logger.info("获取设备日报列表服务,deptIds:{},startDate:{},endDate:{},pageNum:{},pageSize:{}", deptIds, startDate, endDate, pageNum, pageSize);
        PageHelper.startPage(pageNum, pageSize);
        List<MachCurveMapDayDTO> wxMachCurveMapDayDTOS = machDayMapper.selectMultiMachCurveMapDayList(deptIds, startDate, endDate);

        List<AppMachReportDTO> list = new ArrayList();
        for (MachCurveMapDayDTO wxMachCurveMapDayDTO : wxMachCurveMapDayDTOS) {
            AppMachReportDTO appMachReportDTO = new AppMachReportDTO();
            MachReportDataDTO reportDataDTO = new MachReportDataDTO();

            Date date = wxMachCurveMapDayDTO.getDate();
            Double workTimes = wxMachCurveMapDayDTO.getWorkTimes();
            Double idleTimes = wxMachCurveMapDayDTO.getIdleTimes();
            Double oilWear = wxMachCurveMapDayDTO.getOilWear();
            Double efficExp = wxMachCurveMapDayDTO.getEfficExp();
            Double avgTimes = wxMachCurveMapDayDTO.getTotalTimes();
            Integer deptId = wxMachCurveMapDayDTO.getDeptId();

            // 按设备类型统计设备数量
            List<MachTypeAndNumDTO> machTypeList = machDayMapper.selectMachTypeAndNum(deptIds, date, date);

            // 查询时间范围内设备的统计列表
            List<AppMachDataStatDTO> machDataStatDTOList = machDayMapper.selectMachDataStatList(deptIds, date, date);

            // 设备总数量
            Integer totalMachNum = machDataStatDTOList.size();

            reportDataDTO.setAvgIdleTimes(idleTimes);
            reportDataDTO.setAvgOilWear(oilWear);
            reportDataDTO.setAvgTimes(avgTimes);
            reportDataDTO.setAvgWorkTimes(workTimes);
            reportDataDTO.setMachTypeList(machTypeList);
            reportDataDTO.setRankList(machDataStatDTOList);
            reportDataDTO.setTotalMachNum(totalMachNum);
            reportDataDTO.setAvgEfficExp(efficExp);
            reportDataDTO.setTotalTimes(MathUtil.round(avgTimes * totalMachNum, 2));
            reportDataDTO.setTotalIdleTimes(MathUtil.round(idleTimes * totalMachNum, 2));
            reportDataDTO.setTotalWorkTimes(MathUtil.round(workTimes * totalMachNum, 2));

            appMachReportDTO.setDate(date);
            appMachReportDTO.setDeptId(deptId);
            appMachReportDTO.setMachReportDataDTO(reportDataDTO);
            list.add(appMachReportDTO);
        }

        PageInfo<AppMachReportDTO> of = PageInfo.of(list);
        PageInfo<MachCurveMapDayDTO> pageInfo = PageInfo.of(wxMachCurveMapDayDTOS);
        of.setPages(pageInfo.getPages());
        of.setTotal(pageInfo.getTotal());
        return PageUtil.pageData(of);
    }

    @Override
    public PageData<MachDayDataDTO> getDayReportDataDetail(Integer pageNum, Integer pageSize, List<Integer> deptIds, Date date) {
        logger.info("获取设备日报详情服务,deptIds:{},date:{},pageNum:{},pageSize:{}", deptIds, date, pageNum, pageSize);
        PageHelper.startPage(pageNum, pageSize);
        List<MachDayDataDTO> machDataList = machDayMapper.selectMachDayDataDTO(deptIds, date);
        PageHelper.clearPage();
        return PageUtil.pageData(PageInfo.of(machDataList));
    }

    @Override
    public PageData<AppMachReportDTO> getWeekReportDataList(Integer deptId, Integer pageNum, Integer pageSize, Date startDate, Date endDate) {
        logger.info("设备周报列表服务,deptId:{},pageNum:{},pageSize:{},startDate:{},endDate:{}", deptId, pageNum, pageSize, startDate, endDate);
        PageHelper.startPage(pageNum, pageSize);
        List<AppMachReportDTO> list = weekReportMapper.selectByDeptIdAndTime(deptId, startDate, endDate);
        for (AppMachReportDTO appMachReportDTO : list) {
            MachReportDataDTO machReportDataDTO = JSON.parseObject(appMachReportDTO.getReportText(), MachReportDataDTO.class);
            appMachReportDTO.setMachReportDataDTO(machReportDataDTO);
            appMachReportDTO.setReportText(null);
        }
        return PageUtil.pageData(PageInfo.of(list));
    }

    @Override
    public PageData<AppMachWeekReportDTO> getWeekReportDataDetail(List<Integer> deptIds, Integer reportId, Integer pageNum, Integer pageSize) {
        logger.info("设备周报详情服务,deptIds:{},reportId:{},pageNum:{},pageSize:{}", deptIds, reportId, pageNum, pageSize);
        AppMachWeekReport appMachWeekReport = weekReportMapper.selectByPrimaryKey(reportId);
        if (appMachWeekReport == null) {
            throw new BizException(ResultEnum.FAILURE.getCode(), "该设备周报不存在");
        }
        Date startDate = appMachWeekReport.getStartDate();
        Date endDate = appMachWeekReport.getEndDate();

        PageHelper.startPage(pageNum, pageSize);
        List<AppMachWeekReportDTO> list = machDayMapper.selectMach(deptIds, startDate, endDate);
        for (AppMachWeekReportDTO appMachWeekReportDTO : list) {
            Integer machId = appMachWeekReportDTO.getMachId();
            List<WeekReportDetailDTO> appMachDayDateList = machDayMapper.selectMachDayData(machId, startDate, endDate);
            appMachWeekReportDTO.setDateList(appMachDayDateList);
        }
        return PageUtil.pageData(PageInfo.of(list));
    }

    @Override
    public PageData<AppMachReportDTO> getMonthReportDataList(Integer deptId, Integer pageNum, Integer pageSize, Date startMonth, Date endMonth) {
        logger.info("获取设备月报列表服务,deptId:{},pageNum:{},pageSize:{},startMonth:{},endMonth:{}", deptId, pageNum, pageSize, startMonth, endMonth);
        Date startDate = null;
        Date endDate = null;
        if (startMonth != null) {
            startDate = DateUtil.getMonthBegin(startMonth);
        }
        if (endMonth != null) {
            endDate = DateUtil.getMonthEnd(endMonth);
        }

        PageHelper.startPage(pageNum, pageSize);
        List<AppMachReportDTO> list = monthReportMapper.selectByDeptIdAndTime(deptId, startDate, endDate);
        for (AppMachReportDTO appMachReportDTO : list) {
            MachReportDataDTO machReportDataDTO = JSON.parseObject(appMachReportDTO.getReportText(), MachReportDataDTO.class);
            appMachReportDTO.setReportText(null);
            appMachReportDTO.setMachReportDataDTO(machReportDataDTO);
            appMachReportDTO.setMonth(appMachReportDTO.getStartDate());
        }

        return PageUtil.pageData(PageInfo.of(list));
    }

    @Override
    public PageData<AppMachWeekReportDTO> getMonthReportDataDetail(List<Integer> deptIds, Integer reportId, Integer pageNum, Integer pageSize) {
        logger.info("获取设备月报详情服务,deptIds:{},reportId:{},pageNum:{},pageSize:{}", deptIds, reportId, pageNum, pageSize);
        AppMachMonthReport appMachMonthReport = monthReportMapper.selectByPrimaryKey(reportId);
        if (appMachMonthReport == null) {
            throw new BizException(ResultEnum.FAILURE.getCode(), "该设备月报不存在");
        }

        PageHelper.startPage(pageNum, pageSize);
        Date endDate = appMachMonthReport.getEndDate();
        Date startDate = appMachMonthReport.getStartDate();
        List<AppMachWeekReportDTO> list = machDayMapper.selectMach(deptIds, startDate, endDate);
        PageHelper.clearPage();

        for (AppMachWeekReportDTO appMachWeekReportDTO : list) {
            Integer machId = appMachWeekReportDTO.getMachId();
            List<WeekReportDetailDTO> appMachDayDateList = machDayMapper.selectMachDayData(machId, startDate, endDate);
            appMachWeekReportDTO.setDateList(appMachDayDateList);
        }

        return PageUtil.pageData(PageInfo.of(list));
    }


    /**
     * 填充设备月报并上传
     *
     * @param name
     * @param headline
     * @param machList
     * @param deviceType
     * @return
     */
    private String export2MonthReportExcel(Integer deptId, String name, String headline, List<MachMonthReportDTO> machList, Integer deviceType) throws IOException {
        // 获取模板
        ClassPathResource resource = new ClassPathResource("templates/monthReportTemplate.xls");
        InputStream templateFileInputStream = resource.getInputStream();
        File tempFile = FileUtil.copyTemplateFile(templateFileInputStream);
        // 写数据
        FileInputStream fileInputStream = new FileInputStream(tempFile);
        HSSFWorkbook workbook = new HSSFWorkbook(fileInputStream);
        HSSFSheet sheet = workbook.getSheetAt(0);
        // 日期列表
        List<MachDayDataDTO> dateList = machList.get(0).getDataList();
        HSSFCell cell0 = sheet.getRow(0).createCell(0);
        cell0.setCellValue(headline);
        CellRangeAddress cra0 = new CellRangeAddress(0, 0, 0, 2 + dateList.size());
        sheet.addMergedRegion(cra0);
        // 居中
        HSSFCellStyle titleStyle = workbook.createCellStyle();
        titleStyle.setAlignment(HorizontalAlignment.CENTER);
        cell0.setCellStyle(titleStyle);

        HSSFRow row = sheet.getRow(1);
        for (int i = 0; i < dateList.size(); i++) {
            int colIdx = 2 + i;
            Date date = dateList.get(i).getDate();
            String dateStr = dateList.get(i).getMonth();
            if (date != null) {
                dateStr = DateUtil.formatDate(date, "MM-dd");
            }
            HSSFCell cell = row.createCell(colIdx);
            cell.setCellValue(dateStr);
        }
        HSSFCell cell2 = row.createCell(2 + dateList.size());
        cell2.setCellValue("平均值");
        // 填充数据
        int rowIdx = 1;
        for (MachMonthReportDTO machMonthReportDTO : machList) {
            HSSFRow row1 = sheet.createRow(rowIdx + 1);
            HSSFRow row2 = sheet.createRow(rowIdx + 2);
            HSSFRow row3 = sheet.createRow(rowIdx + 3);
            HSSFRow row4 = sheet.createRow(rowIdx + 4);
            HSSFRow row5 = sheet.createRow(rowIdx + 5);
            HSSFRow row6 = sheet.createRow(rowIdx + 6);
            // 合并单元格
            CellRangeAddress cra = new CellRangeAddress(rowIdx + 1, rowIdx + 6, 0, 0);
            sheet.addMergedRegion(cra);

            row1.createCell(0).setCellValue(machMonthReportDTO.getMachTypeName() + machMonthReportDTO.getMachCode());
            row1.createCell(1).setCellValue("开机时长（H）");
            row2.createCell(1).setCellValue("工作时长（H）");
            row3.createCell(1).setCellValue("怠机时长（H）");
            row4.createCell(1).setCellValue("每日油耗（L）");
            if (DeviceType.obd.getValue().equals(deviceType)) {
                row5.createCell(1).setCellValue("放线里程（M）");
                row6.createCell(1).setCellValue("有效工效（M/H）");
            } else if (DeviceType.mach.getValue().equals(deviceType)) {
                row5.createCell(1).setCellValue("工作效率（%）");
                if (ADSQ_PROJECT_ID.equals(deptId)) {
                    row6.createCell(1).setCellValue("现场实际签证工时（H）");
                }
            }

            int colIdx = 0;
            List<MachDayDataDTO> dataList = machMonthReportDTO.getDataList();
            for (int i = 0; i < dataList.size(); i++) {
                MachDayDataDTO detailDTO = dataList.get(i);
                colIdx = i + 2;
                // 开机时长
                Double totalTimes = detailDTO.getTimes();
                row1.createCell(colIdx).setCellValue(totalTimes == null ? "-" : String.valueOf(totalTimes));
                // 工作时长
                Double workTimes = detailDTO.getWorkTimes();
                row2.createCell(colIdx).setCellValue(workTimes == null ? "-" : String.valueOf(workTimes));
                // 怠机时长
                Double idleTimes = detailDTO.getIdleTimes();
                row3.createCell(colIdx).setCellValue(idleTimes == null ? "-" : String.valueOf(idleTimes));
                // 每日油耗
                Double oilWear = detailDTO.getOilWear();
                row4.createCell(colIdx).setCellValue(oilWear == null ? "-" : String.valueOf(oilWear));
                if (DeviceType.obd.getValue().equals(deviceType)) {
                    // 放线里程
                    Long mile = detailDTO.getMile();
                    row5.createCell(colIdx).setCellValue(mile == null ? "-" : String.valueOf(mile));
                    // 有效工效
                    Double mileEfficExp = detailDTO.getMileEfficExp();
                    row6.createCell(colIdx).setCellValue(mileEfficExp == null ? "-" : String.valueOf(mileEfficExp));
                } else if (DeviceType.mach.getValue().equals(deviceType)) {
                    // 工作效率
                    Double efficExp = detailDTO.getEfficExp();
                    row5.createCell(colIdx).setCellValue(efficExp == null ? "-" : String.valueOf(efficExp));
                }
            }
            // 平均值
            row1.createCell(colIdx + 1).setCellValue(machMonthReportDTO.getAvgTimes());
            row2.createCell(colIdx + 1).setCellValue(machMonthReportDTO.getAvgWorkTimes());
            row3.createCell(colIdx + 1).setCellValue(machMonthReportDTO.getAvgIdleTimes());
            row4.createCell(colIdx + 1).setCellValue(machMonthReportDTO.getAvgOilWear());
            if (DeviceType.obd.getValue().equals(deviceType)) {
                row5.createCell(colIdx + 1).setCellValue(machMonthReportDTO.getAvgMile());
                row6.createCell(colIdx + 1).setCellValue(machMonthReportDTO.getAvgMileEfficExp());
            } else if (DeviceType.mach.getValue().equals(deviceType)) {
                row5.createCell(colIdx + 1).setCellValue(machMonthReportDTO.getAvgEfficExp());
            }
            rowIdx += 6;
        }
        // 保存excel
        FileOutputStream fos = new FileOutputStream(tempFile);
        workbook.write(fos);
        fos.flush();
        fos.close();
        // 上传oss
        FileInputStream inputStream = new FileInputStream(tempFile);
        return fileHandler.upload(name, inputStream, FileExpirationRules.oneDay);
    }

    /**
     * 填充设备日报并上传
     *
     * @param list
     * @param name
     * @param date
     * @return
     */
    private String export2DayReportExcel(Integer deptId, List<MachDayDataDTO> list, String name, Date date, Integer deviceType) throws IOException {
        // 获取模板
        ClassPathResource resource = new ClassPathResource("templates/dayReportTemplate.xls");
        InputStream templateFileInputStream = resource.getInputStream();
        File tempFile = FileUtil.copyTemplateFile(templateFileInputStream);

        // 写数据
        FileInputStream fileInputStream = new FileInputStream(tempFile);
        HSSFWorkbook workbook = new HSSFWorkbook(fileInputStream);
        HSSFSheet sheet = workbook.getSheetAt(0);

        // 填充表头
        HSSFCell cell0 = sheet.getRow(0).createCell(0);
        cell0.setCellValue(String.format("%s 设备报表", DateUtil.formatDate(date, "yyyy年MM月dd日")));
        // 居中
        HSSFCellStyle titleStyle = workbook.createCellStyle();
        titleStyle.setAlignment(HorizontalAlignment.CENTER);
        cell0.setCellStyle(titleStyle);

        HSSFRow row1 = sheet.createRow(1);
        row1.createCell(0).setCellValue("设备类型/编号");
        row1.createCell(1).setCellValue("开机时长（H）");
        row1.createCell(2).setCellValue("工作时长（H）");
        if (DeviceType.obd.getValue().equals(deviceType)) {
            row1.createCell(3).setCellValue("怠机时长（H）");
            row1.createCell(4).setCellValue("油耗量（L）");
            row1.createCell(5).setCellValue("放线里程（M）");
            row1.createCell(6).setCellValue("有效工效（M/H）");
        } else if (DeviceType.mach.getValue().equals(deviceType)) {
            row1.createCell(3).setCellValue("怠机时长（H）");
            row1.createCell(4).setCellValue("工作效率（%）");
            row1.createCell(5).setCellValue("油耗量（L）");
            row1.createCell(6).setCellValue("加油量（L）");
        }
        if (ADSQ_PROJECT_ID.equals(deptId)) {
            row1.createCell(7).setCellValue("现场实际签证工时（H）");
        }
        // 填充数据
        int rowIdx = 2;
        for (MachDayDataDTO machDataDTO : list) {
            String machTypeName = machDataDTO.getMachTypeName();
            String machCode = machDataDTO.getMachCode();
            Double times = machDataDTO.getTimes();
            Double idleTimes = machDataDTO.getIdleTimes();
            Double workTimes = machDataDTO.getWorkTimes();
            Double oilWear = machDataDTO.getOilWear();
            Long mile = machDataDTO.getMile();
            Double mileEfficExp = machDataDTO.getMileEfficExp();
            Double efficExp = machDataDTO.getEfficExp();
            Double oilAdd = machDataDTO.getOilAdd();

            HSSFRow row = sheet.createRow(rowIdx);
            row.createCell(0).setCellValue(machTypeName + machCode);
            row.createCell(1).setCellValue(times);
            row.createCell(2).setCellValue(workTimes);
            row.createCell(3).setCellValue(idleTimes);
            if (DeviceType.obd.getValue().equals(deviceType)) {
                row.createCell(4).setCellValue(oilWear);
                row.createCell(5).setCellValue(mile);
                row.createCell(6).setCellValue(mileEfficExp);
            } else if (DeviceType.mach.getValue().equals(deviceType)) {
                row.createCell(4).setCellValue(efficExp);
                row.createCell(5).setCellValue(oilWear);
                row.createCell(6).setCellValue(oilAdd);
            }
            rowIdx += 1;
        }

        //保存excel
        FileOutputStream fos = new FileOutputStream(tempFile);
        workbook.write(fos);
        fos.flush();
        fos.close();

        // 上传oss
        FileInputStream inputStream = new FileInputStream(tempFile);
        return fileHandler.upload(name, inputStream, FileExpirationRules.oneDay);
    }

    /**
     * 设置设备每一天的数据
     */
    private void setDayList(MachMonthReportDTO machDTO, List<MachDayDataDTO> list, Date startDate, Date endDate) {
        Integer machId = machDTO.getMachId();
        List<Date> dateList = DateUtil.getDateListBetween(startDate, endDate);
        List<MachDayDataDTO> dayList = new ArrayList<>(dateList.size());
        for (Date date : dateList) {
            MachDayDataDTO data = new MachDayDataDTO();
            data.setDate(date);
            Iterator<MachDayDataDTO> iterator = list.iterator();
            while (iterator.hasNext()) {
                MachDayDataDTO machDayDataDTO = iterator.next();
                if (machId.equals(machDayDataDTO.getMachId()) && date.equals(machDayDataDTO.getDate())) {
                    BeanUtils.copyProperties(machDayDataDTO, data);
                    iterator.remove();
                }
            }
            dayList.add(data);
        }
        machDTO.setDataList(dayList);
    }

    /**
     * 设置每一个月的数据
     *
     * @param machDTO
     * @param list
     * @param year
     */
    private void setMonthList(MachMonthReportDTO machDTO, List<MachDayDataDTO> list, int year) {
        List<Date> monthList = DateUtil.getMonthListByYear(year);
        Integer machId = machDTO.getMachId();
        List<MachDayDataDTO> dataList = new ArrayList<>(monthList.size());
        for (Date date : monthList) {
            String monthStr = DateUtil.formatDate(date, "yyyy-MM");
            MachDayDataDTO data = new MachDayDataDTO();
            data.setMonth(monthStr);
            Iterator<MachDayDataDTO> iterator = list.iterator();
            while (iterator.hasNext()) {
                MachDayDataDTO machDayDataDTO = iterator.next();
                if (machId.equals(machDayDataDTO.getMachId()) && monthStr.equals(machDayDataDTO.getMonth())) {
                    BeanUtils.copyProperties(machDayDataDTO, data);
                    iterator.remove();
                }
            }
            dataList.add(data);
        }
        machDTO.setDataList(dataList);
    }
}
